library(tidyverse)
library(lubridate)
library(plotly)
library(ggrepel)
countries = c("Austria", "Belgium", "Czechia", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Iceland", "Ireland", "Italy", "Latvia", "Luxembourg", "Netherlands", "Norway", "Poland", "Portugal", "Slovakia", "Slovenia", "Spain", "Sweden", "Switzerland", "United Kingdom", "Canada", "Chile", "Mexico", "Australia", "Japan", "New Zealand", "Israel", "Turkey", "US", "South Korea", "China", "Taiwan*")
df <- read_csv("covid_19_clean_complete.csv")
Parsed with column specification:
cols(
  `Province/State` = col_character(),
  `Country/Region` = col_character(),
  Lat = col_double(),
  Long = col_double(),
  Date = col_character(),
  Confirmed = col_double(),
  Deaths = col_double(),
  Recovered = col_double()
)
pop <- read.csv("API_SP.POP.TOTL_DS2_en_csv_v2_936048.csv")
pop <- tibble(country = pop$Country.Name, pop = pop$X2018)
tests <- read_csv("full-list-covid-19-tests-per-day.csv") %>%
  mutate(tests = `Daily change in cumulative total tests`)
Parsed with column specification:
cols(
  Entity = col_character(),
  Code = col_character(),
  Date = col_character(),
  `Daily change in cumulative total tests` = col_double()
)
options(scipen=999)
covid <- df %>%
  mutate(Date = mdy(Date)) %>%
  group_by(`Country/Region`, Date) %>%
  summarise(Confirmed = sum(Confirmed, na.rm = T),
            Deaths = sum(Deaths, na.rm = T),
            Recovered = sum(Recovered, na.rm = T)) %>%
  arrange(`Country/Region`, Date)


final <- covid %>%
  group_by(`Country/Region`) %>%
  filter(Confirmed >= 100) %>%
  mutate(hunfirst = if_else( Date == min(Date), 1, 0),
         days_since_hun = row_number(),
         marginal_confirmed = Confirmed - lag(Confirmed)) %>%
  left_join( pop %>%
               mutate(country = case_when(
                 country == "United States" ~ "US",
                 country == "Korea, Rep." ~ "South Korea",
                 TRUE ~ as.character(country))), 
             by = c("Country/Region" = "country")) %>%
  drop_na() %>%
  mutate(confirmed_permil = Confirmed/pop*1000000,
         deaths_permil = Deaths/pop*1000000,
         marginal_confirmed_permil = confirmed_permil - lag(confirmed_permil)) %>%
  left_join(tests %>%
              mutate(Date = mdy(Date),
                     Entity = if_else(Entity == "United States", "US", Entity)) %>%
              select(Entity, Date, tests), by = c("Country/Region" = "Entity", "Date"))


final <- final %>%
  left_join(final %>%
              filter(confirmed_permil >= 20) %>%
              group_by(`Country/Region`) %>%
              mutate(days_sinc_twcon = row_number())) %>%
  left_join(final %>%
              filter(deaths_permil >= 3) %>%
              group_by(`Country/Region`) %>%
              mutate(days_sinc_threed = row_number()))
Joining, by = c("Country/Region", "Date", "Confirmed", "Deaths", "Recovered", "hunfirst", "days_since_hun", "marginal_confirmed", "pop", "confirmed_permil", "deaths_permil", "marginal_confirmed_permil", "tests")
Joining, by = c("Country/Region", "Date", "Confirmed", "Deaths", "Recovered", "hunfirst", "days_since_hun", "marginal_confirmed", "pop", "confirmed_permil", "deaths_permil", "marginal_confirmed_permil", "tests")
write_csv(final, "covid_final.csv")
  
graph_confirmed <- final %>%
  filter(`Country/Region` %in% countries,
         days_since_hun < 60) %>%
  ggplot(aes(x = days_since_hun, y = Confirmed, color = `Country/Region`)) + 
  geom_line() + scale_y_log10() + 
  theme_minimal() 
  

last <- final %>%
  filter(`Country/Region` %in% countries,
         days_since_hun < 60) %>%
  group_by(`Country/Region`) %>%
  filter(days_since_hun == max(days_since_hun))

graph <- graph_confirmed + 
  geom_text(aes(x = days_since_hun + 2, y = Confirmed, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
  theme(legend.position = "none") + 
  labs(title = "Confirmed cases by days since 100th case", x = "", y = "")


  
  
plotly <- plotly_build(graph)
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly

NA
graph_confirmed <- final %>%
  filter(`Country/Region` %in% countries,
         days_since_hun < 60) %>%
  ggplot(aes(x = days_since_hun, y = marginal_confirmed, color = `Country/Region`)) + 
  geom_smooth(se=F) + scale_y_log10() + 
  theme_minimal() 
  


graph <- graph_confirmed + 
  geom_text(aes(x = days_since_hun + 2, y = marginal_confirmed, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) + 
  theme(legend.position = "none") + 
  labs(title = "Marginal confirmed cases by days since 100th case", x = "", y = "")


  
  
plotly <- plotly_build(graph)
Transformation introduced infinite values in continuous y-axis`geom_smooth()` using method = 'loess' and formula 'y ~ x'
Removed 22 rows containing non-finite values (stat_smooth).
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
graph_confirmed <- final %>%
  filter(`Country/Region` %in% countries,
         days_since_hun < 60) %>%
  ggplot(aes(x = days_sinc_twcon, y = confirmed_permil, color = `Country/Region`)) + 
  geom_line() + scale_y_log10() + 
  theme_minimal() 
  


graph <- graph_confirmed + 
  geom_text(aes(x = days_sinc_twcon + 2, y = confirmed_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) + 
  theme(legend.position = "none") + 
  labs(title = "Confirmed per 1M  by days since 20th case per 1M", x = "", y = "")


  
  
plotly <- plotly_build(graph)
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly

NA
graph_confirmed <- final %>%
  filter(`Country/Region` %in% countries,
         days_since_hun < 60,
         !is.na(tests)) %>%
  ggplot(aes(x = days_since_hun, y = marginal_confirmed/tests, color = `Country/Region`)) + 
  geom_smooth(se = F) + scale_y_log10() + 
  theme_minimal() 
  


graph <- graph_confirmed + 
  geom_text(aes(x = days_since_hun + 2, y = marginal_confirmed/tests, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) + 
  theme(legend.position = "none") + 
  labs(title = "% of tests confirmed by days since 100th confirmed", x = "", y = "")


  
  
plotly <- plotly_build(graph)
plotly$height <- 900
plotly$width <- 1200
plotly$sizingPolicy$defaultWidth <- 1200
plotly$sizingPolicy$defaultHeight <- 900
plotly
graph_confirmed <- final %>%
  filter(`Country/Region` %in% countries,
         days_since_hun < 60) %>%
  ggplot(aes(x = days_sinc_threed, y = deaths_permil, color = `Country/Region`)) + 
  geom_line() + scale_y_log10() + 
  theme_minimal() 
  


graph <- graph_confirmed + 
  geom_text(aes(x = days_sinc_threed + 2, y = deaths_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) + 
  theme(legend.position = "none") + 
  labs(title = "Deaths per 1M by days since 3rd death per 1M", x = "", y = "")


  
  
plotly <- plotly_build(graph)
Transformation introduced infinite values in continuous y-axis
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQotLS0KdGl0bGU6ICJSIE5vdGVib29rIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGdncmVwZWwpCmNvdW50cmllcyA9IGMoIkF1c3RyaWEiLCAiQmVsZ2l1bSIsICJDemVjaGlhIiwgIkRlbm1hcmsiLCAiRXN0b25pYSIsICJGaW5sYW5kIiwgIkZyYW5jZSIsICJHZXJtYW55IiwgIkdyZWVjZSIsICJIdW5nYXJ5IiwgIkljZWxhbmQiLCAiSXJlbGFuZCIsICJJdGFseSIsICJMYXR2aWEiLCAiTHV4ZW1ib3VyZyIsICJOZXRoZXJsYW5kcyIsICJOb3J3YXkiLCAiUG9sYW5kIiwgIlBvcnR1Z2FsIiwgIlNsb3Zha2lhIiwgIlNsb3ZlbmlhIiwgIlNwYWluIiwgIlN3ZWRlbiIsICJTd2l0emVybGFuZCIsICJVbml0ZWQgS2luZ2RvbSIsICJDYW5hZGEiLCAiQ2hpbGUiLCAiTWV4aWNvIiwgIkF1c3RyYWxpYSIsICJKYXBhbiIsICJOZXcgWmVhbGFuZCIsICJJc3JhZWwiLCAiVHVya2V5IiwgIlVTIiwgIlNvdXRoIEtvcmVhIiwgIkNoaW5hIiwgIlRhaXdhbioiKQpkZiA8LSByZWFkX2NzdigiY292aWRfMTlfY2xlYW5fY29tcGxldGUuY3N2IikKcG9wIDwtIHJlYWQuY3N2KCJBUElfU1AuUE9QLlRPVExfRFMyX2VuX2Nzdl92Ml85MzYwNDguY3N2IikKcG9wIDwtIHRpYmJsZShjb3VudHJ5ID0gcG9wJENvdW50cnkuTmFtZSwgcG9wID0gcG9wJFgyMDE4KQp0ZXN0cyA8LSByZWFkX2NzdigiZnVsbC1saXN0LWNvdmlkLTE5LXRlc3RzLXBlci1kYXkuY3N2IikgJT4lCiAgbXV0YXRlKHRlc3RzID0gYERhaWx5IGNoYW5nZSBpbiBjdW11bGF0aXZlIHRvdGFsIHRlc3RzYCkKb3B0aW9ucyhzY2lwZW49OTk5KQpgYGAKCgpgYGB7cn0KY292aWQgPC0gZGYgJT4lCiAgbXV0YXRlKERhdGUgPSBtZHkoRGF0ZSkpICU+JQogIGdyb3VwX2J5KGBDb3VudHJ5L1JlZ2lvbmAsIERhdGUpICU+JQogIHN1bW1hcmlzZShDb25maXJtZWQgPSBzdW0oQ29uZmlybWVkLCBuYS5ybSA9IFQpLAogICAgICAgICAgICBEZWF0aHMgPSBzdW0oRGVhdGhzLCBuYS5ybSA9IFQpLAogICAgICAgICAgICBSZWNvdmVyZWQgPSBzdW0oUmVjb3ZlcmVkLCBuYS5ybSA9IFQpKSAlPiUKICBhcnJhbmdlKGBDb3VudHJ5L1JlZ2lvbmAsIERhdGUpCgoKZmluYWwgPC0gY292aWQgJT4lCiAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCkgJT4lCiAgZmlsdGVyKENvbmZpcm1lZCA+PSAxMDApICU+JQogIG11dGF0ZShodW5maXJzdCA9IGlmX2Vsc2UoIERhdGUgPT0gbWluKERhdGUpLCAxLCAwKSwKICAgICAgICAgZGF5c19zaW5jZV9odW4gPSByb3dfbnVtYmVyKCksCiAgICAgICAgIG1hcmdpbmFsX2NvbmZpcm1lZCA9IENvbmZpcm1lZCAtIGxhZyhDb25maXJtZWQpKSAlPiUKICBsZWZ0X2pvaW4oIHBvcCAlPiUKICAgICAgICAgICAgICAgbXV0YXRlKGNvdW50cnkgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgY291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyIgfiAiVVMiLAogICAgICAgICAgICAgICAgIGNvdW50cnkgPT0gIktvcmVhLCBSZXAuIiB+ICJTb3V0aCBLb3JlYSIsCiAgICAgICAgICAgICAgICAgVFJVRSB+IGFzLmNoYXJhY3Rlcihjb3VudHJ5KSkpLCAKICAgICAgICAgICAgIGJ5ID0gYygiQ291bnRyeS9SZWdpb24iID0gImNvdW50cnkiKSkgJT4lCiAgZHJvcF9uYSgpICU+JQogIG11dGF0ZShjb25maXJtZWRfcGVybWlsID0gQ29uZmlybWVkL3BvcCoxMDAwMDAwLAogICAgICAgICBkZWF0aHNfcGVybWlsID0gRGVhdGhzL3BvcCoxMDAwMDAwLAogICAgICAgICBtYXJnaW5hbF9jb25maXJtZWRfcGVybWlsID0gY29uZmlybWVkX3Blcm1pbCAtIGxhZyhjb25maXJtZWRfcGVybWlsKSkgJT4lCiAgbGVmdF9qb2luKHRlc3RzICU+JQogICAgICAgICAgICAgIG11dGF0ZShEYXRlID0gbWR5KERhdGUpLAogICAgICAgICAgICAgICAgICAgICBFbnRpdHkgPSBpZl9lbHNlKEVudGl0eSA9PSAiVW5pdGVkIFN0YXRlcyIsICJVUyIsIEVudGl0eSkpICU+JQogICAgICAgICAgICAgIHNlbGVjdChFbnRpdHksIERhdGUsIHRlc3RzKSwgYnkgPSBjKCJDb3VudHJ5L1JlZ2lvbiIgPSAiRW50aXR5IiwgIkRhdGUiKSkKCgpmaW5hbCA8LSBmaW5hbCAlPiUKICBsZWZ0X2pvaW4oZmluYWwgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKGNvbmZpcm1lZF9wZXJtaWwgPj0gMjApICU+JQogICAgICAgICAgICAgIGdyb3VwX2J5KGBDb3VudHJ5L1JlZ2lvbmApICU+JQogICAgICAgICAgICAgIG11dGF0ZShkYXlzX3NpbmNfdHdjb24gPSByb3dfbnVtYmVyKCkpKSAlPiUKICBsZWZ0X2pvaW4oZmluYWwgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKGRlYXRoc19wZXJtaWwgPj0gMykgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCkgJT4lCiAgICAgICAgICAgICAgbXV0YXRlKGRheXNfc2luY190aHJlZWQgPSByb3dfbnVtYmVyKCkpKQoKd3JpdGVfY3N2KGZpbmFsLCAiY292aWRfZmluYWwuY3N2IikKICAKCmBgYAoKCgoKCgoKYGBge3J9CmdyYXBoX2NvbmZpcm1lZCA8LSBmaW5hbCAlPiUKICBmaWx0ZXIoYENvdW50cnkvUmVnaW9uYCAlaW4lIGNvdW50cmllcywKICAgICAgICAgZGF5c19zaW5jZV9odW4gPCA2MCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5c19zaW5jZV9odW4sIHkgPSBDb25maXJtZWQsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCkpICsgCiAgZ2VvbV9saW5lKCkgKyBzY2FsZV95X2xvZzEwKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCiAgCgpsYXN0IDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgY291bnRyaWVzLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBncm91cF9ieShgQ291bnRyeS9SZWdpb25gKSAlPiUKICBmaWx0ZXIoZGF5c19zaW5jZV9odW4gPT0gbWF4KGRheXNfc2luY2VfaHVuKSkKCmdyYXBoIDwtIGdyYXBoX2NvbmZpcm1lZCArIAogIGdlb21fdGV4dChhZXMoeCA9IGRheXNfc2luY2VfaHVuICsgMiwgeSA9IENvbmZpcm1lZCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gLCBsYWJlbCA9IGBDb3VudHJ5L1JlZ2lvbmApLCBkYXRhID0gbGFzdCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICJDb25maXJtZWQgY2FzZXMgYnkgZGF5cyBzaW5jZSAxMDB0aCBjYXNlIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5IDwtIHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA8LSA5MDAKcGxvdGx5JHdpZHRoIDwtIDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPC0gOTAwCnBsb3RseQogCmBgYAoKCgoKYGBge3J9CmdyYXBoX2NvbmZpcm1lZCA8LSBmaW5hbCAlPiUKICBmaWx0ZXIoYENvdW50cnkvUmVnaW9uYCAlaW4lIGNvdW50cmllcywKICAgICAgICAgZGF5c19zaW5jZV9odW4gPCA2MCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5c19zaW5jZV9odW4sIHkgPSBtYXJnaW5hbF9jb25maXJtZWQsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCkpICsgCiAgZ2VvbV9zbW9vdGgoc2U9RikgKyBzY2FsZV95X2xvZzEwKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCiAgCgoKZ3JhcGggPC0gZ3JhcGhfY29uZmlybWVkICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZGF5c19zaW5jZV9odW4gKyAyLCB5ID0gbWFyZ2luYWxfY29uZmlybWVkLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICJNYXJnaW5hbCBjb25maXJtZWQgY2FzZXMgYnkgZGF5cyBzaW5jZSAxMDB0aCBjYXNlIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5IDwtIHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA8LSA5MDAKcGxvdGx5JHdpZHRoIDwtIDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPC0gOTAwCnBsb3RseQpgYGAKCgoKCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkIDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgY291bnRyaWVzLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNfdHdjb24sIHkgPSBjb25maXJtZWRfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fbGluZSgpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgdGhlbWVfbWluaW1hbCgpIAogIAoKCmdyYXBoIDwtIGdyYXBoX2NvbmZpcm1lZCArIAogIGdlb21fdGV4dChhZXMoeCA9IGRheXNfc2luY190d2NvbiArIDIsIHkgPSBjb25maXJtZWRfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICJDb25maXJtZWQgcGVyIDFNICBieSBkYXlzIHNpbmNlIDIwdGggY2FzZSBwZXIgMU0iLCB4ID0gIiIsIHkgPSAiIikKCgogIAogIApwbG90bHkgPC0gcGxvdGx5X2J1aWxkKGdyYXBoKQpwbG90bHkkaGVpZ2h0IDwtIDkwMApwbG90bHkkd2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRXaWR0aCA8LSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdEhlaWdodCA8LSA5MDAKcGxvdGx5CiAKYGBgCgoKCgoKCgoKCgpgYGB7ciBldmFsPUZBTFNFfQpncmFwaF9jb25maXJtZWQgPC0gZmluYWwgJT4lCiAgZmlsdGVyKGBDb3VudHJ5L1JlZ2lvbmAgJWluJSBjb3VudHJpZXMsCiAgICAgICAgIGRheXNfc2luY2VfaHVuIDwgNjAsCiAgICAgICAgICFpcy5uYSh0ZXN0cykpICU+JQogIGdncGxvdChhZXMoeCA9IGRheXNfc2luY2VfaHVuLCB5ID0gbWFyZ2luYWxfY29uZmlybWVkL3Rlc3RzLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fc21vb3RoKHNlID0gRikgKyBzY2FsZV95X2xvZzEwKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCiAgCgoKZ3JhcGggPC0gZ3JhcGhfY29uZmlybWVkICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZGF5c19zaW5jZV9odW4gKyAyLCB5ID0gbWFyZ2luYWxfY29uZmlybWVkL3Rlc3RzLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICIlIG9mIHRlc3RzIGNvbmZpcm1lZCBieSBkYXlzIHNpbmNlIDEwMHRoIGNvbmZpcm1lZCIsIHggPSAiIiwgeSA9ICIiKQoKCiAgCiAgCnBsb3RseSA8LSBwbG90bHlfYnVpbGQoZ3JhcGgpCnBsb3RseSRoZWlnaHQgPC0gOTAwCnBsb3RseSR3aWR0aCA8LSAxMjAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdFdpZHRoIDwtIDEyMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0SGVpZ2h0IDwtIDkwMApwbG90bHkKYGBgCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkIDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgY291bnRyaWVzLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNfdGhyZWVkLCB5ID0gZGVhdGhzX3Blcm1pbCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gKSkgKyAKICBnZW9tX2xpbmUoKSArIHNjYWxlX3lfbG9nMTAoKSArIAogIHRoZW1lX21pbmltYWwoKSAKICAKCgpncmFwaCA8LSBncmFwaF9jb25maXJtZWQgKyAKICBnZW9tX3RleHQoYWVzKHggPSBkYXlzX3NpbmNfdGhyZWVkICsgMiwgeSA9IGRlYXRoc19wZXJtaWwsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCwgbGFiZWwgPSBgQ291bnRyeS9SZWdpb25gKSwgZGF0YSA9IGxhc3QsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIkRlYXRocyBwZXIgMU0gYnkgZGF5cyBzaW5jZSAzcmQgZGVhdGggcGVyIDFNIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5IDwtIHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA8LSA5MDAKcGxvdGx5JHdpZHRoIDwtIDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPC0gOTAwCnBsb3RseQpgYGAKCgoKCgoKCgoKCgoKCgoKCgo=